package com.fingard.dsp.bank.directbank.nnbill01;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.security.KeyStore;
import java.util.zip.ZipInputStream;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.SendBankRespose;
import com.fingard.text.StringHelper;

public class SmsPost {

	public static SendBankRespose sendPost(String p_url, ActSetItem p_actItem, String p_reqXml, String p_charset) throws Exception{
		
		System.setProperty("jsse.enableSNIExtension", "false");
		SendBankRespose retResp = new SendBankRespose();
		
		FileInputStream fis = null;
		KeyStore ks = null;
		KeyManagerFactory kmf = null;
		TrustManager[] tm = { new MyX509TrustManager() };//同位体验证信任决策源//同位体验证可信任的证书来源
		SSLContext sslContext = null;
		SSLSocketFactory factory = null;
		try{
			String ksPath = p_actItem.ownKeyStorePath.toLowerCase();
	        String ksType = "PKCS12";
	        if(ksPath.endsWith("jks")){
	        	ksType = "JKS";
	        }
	        ks = KeyStore.getInstance(ksType);//"PKCS12"、"JKS"
			fis = new FileInputStream(p_actItem.ownKeyStorePath);
	        char[] keyPassword = null;
	        if (StringHelper.hasAnyChar(p_actItem.ownKeyPassword)){
	        	keyPassword = p_actItem.ownKeyPassword.toCharArray();
	        }
	        ks.load(fis, keyPassword);
	        fis.close();
	        fis = null;
	        
	      //创建用于管理JKS密钥库的密钥管理器
			kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
			//初始化证书
			kmf.init(ks, p_actItem.ownKeyPassword.toCharArray());
			
			//初始化安全套接字
			sslContext = SSLContext.getInstance("TLSv1.2");
			//初始化SSL环境。第二个参数是告诉JSSE使用的可信任证书的来源，设置为null是从javax.net.ssl.trustStore中获得证书。
			//第三个参数是JSSE生成的随机数，这个参数将影响系统的安全性，设置为null是个好选择，可以保证JSSE的安全性。
			sslContext.init(kmf.getKeyManagers(),tm, null);
			
			//根据上面配置的SSL上下文来产生SSLSocketFactory,与通常的产生方法不同
			factory = sslContext.getSocketFactory();
		}
		catch(Exception ex){
			retResp.connState = FailCode.E9981;
			retResp.retMessage = ex.getMessage();
			retResp.appendLog(ex);
			return retResp;
		}
		finally{
			if(fis != null){
				fis.close();
			}
		}
		OutputStream out = null;
		HttpsURLConnection conn = null;
		try{
			//com.sun.net.ssl.internal.www.protocol.https.Handler()
			//sun.net.www.protocol.https.Handler()
			//sun.net.www.protocol.https.HttpsURLConnectionImpl aa = null;
			//aa.setSSLSocketFactory(sf)
			//sun.net.www.protocol.https.Handler()
			//retResp.appendLog("\r\nsetProperty https.protocols TLSv1");
			//System.setProperty("https.protocols", "TLSv1");
		    URL realUrl = new URL(null,p_url, new sun.net.www.protocol.https.Handler());//new URL(p_url);
		    //打开和URL之间的连接
		    conn = (HttpsURLConnection)realUrl.openConnection();
		}
		catch(Exception ex){
			retResp.connState = FailCode.E9999;
			retResp.retMessage = ex.getMessage();
			retResp.appendLog(ex);
			return retResp;
		}
		try{
		    //创建安全的连接套接字
			conn.setSSLSocketFactory(factory);
		    //发送POST请求必须设置如下两行,使用 URL 连接进行输出、入
		    conn.setDoOutput(true);
		    conn.setDoInput(true);
		    //设置URL连接的超时时限
		    conn.setReadTimeout(30000);
		    
		    //设置通用的请求属性
		    String authString = p_actItem.merchantId + ":" + p_actItem.userFlag;
			String auth = "Basic " + Base64Binrary.encodeBase64Binrary(authString.getBytes());
		    conn.setRequestProperty("Authorization", auth);//授权
		    
		    // 获取URLConnection对象对应的输出流
		    out = conn.getOutputStream();
		    //发送请求参数
			out.write(p_reqXml.getBytes(p_charset));
		 
		    //flush 输出流的缓冲
		    out.flush();
	        
		    //得到服务端返回
		 	InputStream is = conn.getInputStream();
		    if(is!=null && !"".equals(is)){
		    	ByteArrayOutputStream bos = new ByteArrayOutputStream();
				byte[] receiveBuffer = new byte[2048];//缓冲区长度
				int readBytesSize = is.read(receiveBuffer);//读取数据长度，InputStream要读取的数据长度一定要小于等于缓冲区中的字节数
					
				while(readBytesSize != -1){//判断流是否位于文件末尾而没有可用的字节
					bos.write(receiveBuffer, 0, readBytesSize);//从receiveBuffer内存处的0偏移开始写，写与readBytesSize长度相等的字节
					readBytesSize = is.read(receiveBuffer);
				}
				retResp.retMessage = new String(bos.toByteArray(), p_charset);//编码后的tr2报文
		    }
		    is.close();
		    out.close();
		    out = null;
		    conn.disconnect();
	    }
	    catch(Exception e){
	    	retResp.appendLog(e);
	    	retResp.retMessage = e.getMessage();
	    }
	    finally{
	    	if (out != null){out.close();}
	    }
		return retResp;
	}

	public static SendBankRespose sendGet(String p_url, ActSetItem p_actItem, String p_reqStr, String p_charset) throws Exception{
		System.setProperty("jsse.enableSNIExtension", "false");
		SendBankRespose retResp = new SendBankRespose();
		
		FileInputStream fis = null;
		KeyStore ks = null;
		KeyManagerFactory kmf = null;
		TrustManager[] tm = { new MyX509TrustManager() };//同位体验证信任决策源//同位体验证可信任的证书来源
		SSLContext sslContext = null;
		SSLSocketFactory factory = null;
		try{
			String ksPath = p_actItem.ownKeyStorePath.toLowerCase();
	        String ksType = "PKCS12";
	        if(ksPath.endsWith("jks")){
	        	ksType = "JKS";
	        }
	        ks = KeyStore.getInstance(ksType);//"PKCS12"、"JKS"
			fis = new FileInputStream(p_actItem.ownKeyStorePath);
	        char[] keyPassword = null;
	        if (StringHelper.hasAnyChar(p_actItem.ownKeyPassword)){
	        	keyPassword = p_actItem.ownKeyPassword.toCharArray();
	        }
	        ks.load(fis, keyPassword);
	        fis.close();
	        fis = null;
	        
	      //创建用于管理JKS密钥库的密钥管理器
			kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
			//初始化证书
			kmf.init(ks, p_actItem.ownKeyPassword.toCharArray());
			
			//初始化安全套接字
			sslContext = SSLContext.getInstance("SSL");
			//初始化SSL环境。第二个参数是告诉JSSE使用的可信任证书的来源，设置为null是从javax.net.ssl.trustStore中获得证书。
			//第三个参数是JSSE生成的随机数，这个参数将影响系统的安全性，设置为null是个好选择，可以保证JSSE的安全性。
			sslContext.init(kmf.getKeyManagers(),tm, null);
			
			//根据上面配置的SSL上下文来产生SSLSocketFactory,与通常的产生方法不同
			factory = sslContext.getSocketFactory();
		}
		catch(Exception ex){
			retResp.connState = FailCode.E9981;
			retResp.retMessage = ex.getMessage();
			retResp.appendLog(ex);
			return retResp;
		}
		finally{
			if(fis != null){
				fis.close();
			}
		}
//		OutputStream out = null;
		HttpsURLConnection conn = null;
		try{
		    URL realUrl = new URL(p_url+"?"+p_reqStr);
		    //打开和URL之间的连接
		    conn = (HttpsURLConnection)realUrl.openConnection();
		}
		catch(Exception ex){
			retResp.connState = FailCode.E9999;
			retResp.retMessage = ex.getMessage();
			retResp.appendLog(ex);
			return retResp;
		}
		try{
		    //创建安全的连接套接字
			conn.setSSLSocketFactory(factory);
		    //发送POST请求必须设置如下两行,使用 URL 连接进行输出、入
//		    conn.setDoOutput(true);
//		    conn.setDoInput(true);
		    //设置URL连接的超时时限
		    conn.setReadTimeout(30000);
		    
		    //设置通用的请求属性
		    String authString = p_actItem.merchantId + ":" + p_actItem.userFlag;
			String auth = "Basic " + Base64Binrary.encodeBase64Binrary(authString.getBytes());
		    conn.setRequestProperty("Authorization", auth);//授权
		    
		    conn.connect();
		    
		    // 获取URLConnection对象对应的输出流
//		    out = conn.getOutputStream();
		    //发送请求参数
//			out.write(p_reqStr.getBytes(p_charset));
		 
		    //flush 输出流的缓冲
//		    out.flush();
	        
		    //得到服务端返回
		 	InputStream is = conn.getInputStream();
		    if(is!=null && !"".equals(is)){
		    	ByteArrayOutputStream bos = new ByteArrayOutputStream();
				byte[] receiveBuffer = new byte[2048];//缓冲区长度
				int readBytesSize = is.read(receiveBuffer);//读取数据长度，InputStream要读取的数据长度一定要小于等于缓冲区中的字节数
					
				while(readBytesSize != -1){//判断流是否位于文件末尾而没有可用的字节
					bos.write(receiveBuffer, 0, readBytesSize);//从receiveBuffer内存处的0偏移开始写，写与readBytesSize长度相等的字节
					readBytesSize = is.read(receiveBuffer);
				}
				byte[] recBytes = bos.toByteArray();
				System.out.println("返回的压缩内容:"+new String(recBytes, p_charset));
				byte[] b = null;
				try {
					ByteArrayInputStream bis = new ByteArrayInputStream(recBytes);
					ZipInputStream zip = new ZipInputStream(bis);
					byte[] buf = new byte[1024];
					int num = -1;
					ByteArrayOutputStream baos = new ByteArrayOutputStream();
					while((num = zip.read(buf, 0, buf.length))!= -1) {
						baos.write(buf,0,num);
					}
					b = baos.toByteArray();
					baos.flush();
					baos.close();
					zip.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
				//System.out.println("返回的解压内容:"+new String(b, p_charset));
				retResp.retMessage = new String(b, p_charset);//编码后的tr2报文
		    }
		    is.close();
//		    out.close();
//		    out = null;
		    conn.disconnect();
	    }
	    catch(Exception e){
	    	retResp.appendLog(e);
	    	retResp.retMessage = e.getMessage();
	    }
//	    finally{
//	    	if (out != null){out.close();}
//	    }
		return retResp;
	}
}
